﻿using Microsoft.IdentityModel.Tokens;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace AbpProjectTemplate.OpenIddict
{
    public static class OpeniddictHelper
    {
        public enum CertificateType
        {
            Signing,
            Encryption
        }

        /// <summary>
        /// 创建或者返回证书，type1为签名 其它为加密
        /// </summary>
        public static X509Certificate2 CreateOrGetCertificate(string path,
                                                        CertificateType type,
                                                        TimeSpan expTime,
                                                        string password = null)
        {
            //https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html
            if (File.Exists(path) && File.GetCreationTime(path) > DateTimeOffset.UtcNow.Add(-expTime))
                return X509CertificateLoader.LoadPkcs12(File.ReadAllBytes(path), password);
            var dir = Path.GetDirectoryName(path);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            var subject = type == CertificateType.Signing
                ? "CN=Fabrikam Signing Certificate"
                : "CN=Fabrikam Encryption Certificate";
            var keyUsageFlags = type == CertificateType.Signing
                ? X509KeyUsageFlags.DigitalSignature
                : X509KeyUsageFlags.KeyEncipherment;
            using (var algorithm = RSA.Create(keySizeInBits: 2048))
            {
                var distinguishedName = new X500DistinguishedName(subject);
                var request = new CertificateRequest(distinguishedName, algorithm, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                request.CertificateExtensions.Add(new X509KeyUsageExtension(keyUsageFlags, critical: true));
                var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.Add(expTime));

                File.WriteAllBytes(path, certificate.Export(X509ContentType.Pfx, password));
                //builder.AddSigningCertificate(certificate);
                return certificate;
            }
        }

        public static SecurityKey CreateKey(string key) 
        {
            return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
        }
    }
}
